package org.budo.wxpay;

import java.util.Map;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;

import org.budo.support.java.net.util.JavaNetUtil;
import org.budo.support.lang.util.StringUtil;
import org.budo.support.mvcs.Mvcs;
import org.budo.support.spring.util.SpringUtil;
import org.budo.wxpay.util.WxpayXmlUtil;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public class BudoWxpaySupport {
    protected String buildSignTestParameters() {
        BudoWxpayConfig conf = SpringUtil.getBean(BudoWxpayConfig.class);

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", conf.getAppId());
        parameters.put("mch_id", conf.getMerchId());
        parameters.put("nonce_str", this.createNoncestr(16));

        String requestXML = null;
        try {
            String sign = this.buildSign("UTF-8", parameters, conf.getApiKey());
            requestXML = this.buildRequestXml(parameters, sign);
        } catch (Exception e) {
            throw new RuntimeException("生成随机字符串时异常", e);
        }
        return requestXML;
    }

    protected String createNoncestr(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    protected SortedMap<Object, Object> parameters_JSAPI(String bussinessId, String desc, Double amount, String notifyurl) {
        log.info("#25 getPayParam, bussinessId=" + bussinessId);
        BudoWxpayConfig conf = SpringUtil.getBean(BudoWxpayConfig.class);

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", conf.getAppId());
        parameters.put("mch_id", conf.getMerchId());
        parameters.put("device_info", "WEB");
        parameters.put("nonce_str", this.createNoncestr(16));
        parameters.put("body", desc);
        parameters.put("out_trade_no", bussinessId);
        parameters.put("total_fee", amount.intValue());
        parameters.put("notify_url", notifyurl);

        // 在微信里面
        parameters.put("trade_type", TradeType.JSAPI);
        parameters.put("openid", Mvcs.getSessionAttribute("_wx_jsapi_openid"));

        String remoteAddr = Mvcs.getRemoteAddr(Mvcs.getRequest()); /*  */ // 171.221.206.238
        if (StringUtil.startsWith(remoteAddr, "192.168.6.") || StringUtil.startsWith(remoteAddr, "192.168.4.")) { // 如果内网环境
            remoteAddr = "171.221.206.238"; // 研发办公室的公网ip
        }

        parameters.put("spbill_create_ip", remoteAddr); // 客户端IP要求与下一步跳转后访问的一致

        log.info("#66 parameters=" + parameters);
        return parameters;
    }

    public SortedMap<Object, Object> parameters_NATIVE(String bussinessId, String desc, Double amount, String notifyurl) {
        BudoWxpayConfig conf = SpringUtil.getBean(BudoWxpayConfig.class);
        log.info("#105 getPayParam, bussinessId=" + bussinessId);

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", conf.getAppId());
        parameters.put("mch_id", conf.getMerchId());
        parameters.put("device_info", "WEB");
        parameters.put("nonce_str", this.createNoncestr(16));
        parameters.put("body", desc);
        parameters.put("out_trade_no", bussinessId);
        parameters.put("total_fee", amount.intValue());
        parameters.put("notify_url", notifyurl);

        parameters.put("trade_type", TradeType.NATIVE); // NATIVE
        parameters.put("spbill_create_ip", JavaNetUtil.getLocalHostAddress()); // 这个是不是也要改哦
        return parameters;
    }

    protected String buildRequestXml(SortedMap<Object, Object> parameters, String sign) {
        return WxpayXmlUtil.buildRequestXml(parameters, sign);
    }

    protected String buildSign(String characterEncoding, SortedMap<Object, Object> parameters, String apiKey) {
        return WxpayXmlUtil.buildSign(characterEncoding, parameters, apiKey);
    }

    protected SortedMap<Object, Object> parameters_MWEB(String bussinessId, String desc, Double amount, String notifyurl) {
        log.info("#25 getPayParam, bussinessId=" + bussinessId);
        BudoWxpayConfig conf = SpringUtil.getBean(BudoWxpayConfig.class);

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", conf.getAppId());
        parameters.put("mch_id", conf.getMerchId());
        parameters.put("nonce_str", this.createNoncestr(16));
        parameters.put("sign_type", "MD5");
        parameters.put("body", desc);
        parameters.put("out_trade_no", bussinessId);
        parameters.put("total_fee", amount.intValue());
        String remoteAddr = Mvcs.getRemoteAddr(Mvcs.getRequest()); /*  */ // 171.221.206.238
        if (StringUtil.startsWith(remoteAddr, "192.168.6.") || StringUtil.startsWith(remoteAddr, "192.168.4.")) { // 如果内网环境
            remoteAddr = "171.221.206.238"; // 研发办公室的公网ip
        }
        parameters.put("spbill_create_ip", remoteAddr); // 客户端IP要求与下一步跳转后访问的一致
        parameters.put("notify_url", notifyurl);
        parameters.put("trade_type", TradeType.MWEB);
        parameters.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://pay.qq.com\",\"wap_name\": \"腾讯充值\"}}");

        log.info("#66 parameters=" + parameters);
        return parameters;
    }

    protected Map<String, String> parseXmlToMap(String xml) {
        return WxpayXmlUtil.parseXmlToMap(xml);
    }

    protected SortedMap<Object, Object> params_0(BudoWxpayConfig conf, String prepay_id) {
        SortedMap<Object, Object> payParamMap = new TreeMap<Object, Object>();
        // 组装微信公众号支付所需要的参数 ，见
        // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6#
        // 这里的参数名称不能修改，因为需要根据参数名称和值生成签名串
        payParamMap.put("appId", conf.getAppId());
        payParamMap.put("timeStamp", String.valueOf(System.currentTimeMillis()));
        payParamMap.put("nonceStr", this.createNoncestr(16));
        payParamMap.put("package", "prepay_id=".concat(prepay_id));
        payParamMap.put("signType", conf.getSignMethod());
        String paySign = WxpayXmlUtil.buildSign("UTF-8", payParamMap, conf.getApiKey());
        payParamMap.put("paySign", paySign);
        return payParamMap;
    }

    /**
     * 构建下单参数
     * 
     * @param bussinessId
     * @param desc
     * @param amount
     * @param notifyurl
     */
    protected String getPayParam_JSAPI(String bussinessId, String desc, Double amount, String openId) throws Exception {
        BudoWxpayConfig conf = SpringUtil.getBean(BudoWxpayConfig.class);

        SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
        parameters.put("appid", conf.getAppId());
        parameters.put("mch_id", conf.getMerchId());
        parameters.put("device_info", "WEB");
        parameters.put("nonce_str", this.createNoncestr(16));
        parameters.put("body", desc);
        parameters.put("out_trade_no", bussinessId);
        parameters.put("total_fee", amount);
        parameters.put("spbill_create_ip", JavaNetUtil.getLocalHostAddress());
        parameters.put("notify_url", conf.getNotifyUrl());
        parameters.put("trade_type", TradeType.JSAPI);
        parameters.put("openid", openId);

        String sign = WxpayXmlUtil.buildSign("UTF-8", parameters, conf.getApiKey());
        parameters.put("sign", sign);

        String requestXML = WxpayXmlUtil.buildRequestXml(parameters, sign);

        return requestXML;
    }
}